<template>
    <div class="wl-tooltip" v-on="outerEvents">
        <!-- 触发的元素 -->
        <div class="wl-tooltip" ref="triggleRef" v-on="events">
            <slot></slot>
        </div>
        <!-- 显示的元素 -->
        <div class="wl-tooltip__popper" ref="popperRef" v-if="isOpen">
            <slot name="content">{{ content }}</slot>
            <!-- 箭头 -->
            <div id="arrow" data-popper-arrow></div>
        </div>
    </div>
</template>

<script setup lang="ts">
import { ref, useTemplateRef, watch, reactive, computed } from 'vue'
import { debounce } from 'lodash-es'
import { createPopper } from '@popperjs/core'
import propsObj from './props'
const triggleRef = useTemplateRef('triggleRef')
const popperRef = useTemplateRef('popperRef')
let popperInstance = null
defineOptions({
    name: 'wl-tooltip'
})
const props = defineProps(propsObj)
const emit = defineEmits(['visible-change'])
// 这里创建一个计算属性，该计算属性用于构建 createPopper 方法的第三个参数
const popperOptions = computed(() => ({
    placement: props.placement,
    modifiers: [
        {
            name: 'offset',
            options: {
                offset: [0, 6]
            }
        }
    ]
}))
// 改对象用于存储各种事件
const events = reactive<{
    click?: () => void
    mouseenter?: () => void
}>({})
const outerEvents = reactive<{
    mouseleave?: () => void
}>({})
const openDebounce = debounce(() => {
    isOpen.value = true
    emit('visible-change', true)
}, props.openDelay)

const closeDebounce = debounce(() => {
    isOpen.value = false
    emit('visible-change', false)
}, props.closeDelay)
const open = () => {
    closeDebounce.cancel()
    openDebounce()
}
const close = () => {
    openDebounce.cancel()
    closeDebounce()
}
// 提示框是否要显示出来
const isOpen = ref(false)
// 接下来需要创建具体的popper实例
// poper实例应该是在isOpen发生变化的时候创建
watch(isOpen, (newValue) => {
    if (newValue) {
        if (triggleRef.value && triggleRef.value) {
            // 创建popper实例
            popperInstance = createPopper(triggleRef.value, popperRef.value, popperOptions.value)
        }
    } else {
        popperInstance?.destroy()
    }
}, {
    flush: 'post'
})
// 给触发元素绑定相应的事件


// 调用attacthEvents方法就能够给触发元素绑定事件
const attachEvents = () => {
    // 判断触发方式
    if (props.trigger === 'hover') {
        events['mouseenter'] = open
        outerEvents['mouseleave'] = close
    } else if (props.trigger === 'click') {
        events['click'] = () => isOpen.value ? close() : open()
    }
}
if (!props.manual) {
    attachEvents()
}
// 这里我们需要给用户提供两个方法，让用户可以手动打开和关闭提示框
defineExpose({
    show: open,
    hide: close
})
</script>

<style scoped lang="scss"></style>